#tracks the entire game

load 'etc/dominoes_exceptions.rb'
load 'etc/input_helper.rb'
load 'player_types/player.rb'
load 'player_types/opponent_player.rb'
load 'player_types/human_player.rb'
load 'pool.rb'
load 'domino.rb'
load 'board.rb'
load 'evaluation_functions.rb'
load 'dominoes_game_functions.rb'
load 'dominoes_dup_state.rb'
load 'prob_hash.rb'
load 'features/scoring_points.rb'

require 'logger'
require 'fileutils'


class DominoesGame
  attr_reader :player, :opp, :board, :pool, :started
  
  include EvaluationFunctions
  include InputHelper
  include Features
  include DominoesGameFunctions
  
  WILDCARD = "*"
  SCORER = 5
  TARGET_POINTS = 100
  
  def initialize(n, debug = true, comp_v_comp = false)
    
    init_logger
        
    @pool = Pool.new n
    EvaluationFunctions.init(n)
    @board = Board.new
    @prob_hash = ProbHash.new
    @player = HumanPlayer.new "me", @board, @pool, @prob_hash
    @opp = OpponentPlayer.new "opp", @board, @pool, @prob_hash
    @started = true
    $debug = debug
  end
  
  def start
    begin
      raise GameNotStartedError unless @started
      start_game
    rescue Exception => e
      puts "Dominoes CRASH! \n #{e.message + "\n" + e.backtrace.join("\n")}"
      $logger.info "Dominoes AI CRASH!!"
      $logger.debug e.message + "\n"
      $logger.debug e.backtrace.join("\n")
    end
  end
  
  def dup_state
    board,pool,prob_hash = @board.dup, @pool.dup, @prob_hash.dup
    player,opp = @player.dup(board,pool,prob_hash), @opp.dup(board,pool,prob_hash)
    dds = DominoesDupState.new(player, opp, board, pool, prob_hash, @players_play)
    dds
  end
  
  #private
  
  def start_game
    set_initial_score
    @players_play = get_first_player
    @player.init_hand
    @opp.init_hand(@player.hand.size)
    init_prob_hash
    
    while !(previous_won ||= false)
      
      print_state
      log_state
      
      previous_won = if @players_play
        players_turn
      else
        opps_turn
      end
      previous_won = check_winner
      @players_play = !@players_play
    end
    
    puts "GAME OVER: !!"
    print_state
    
  end
  
  def players_turn
    puts "hand is #{@player.hand}"
    
    while !(valid_play ||= false)
      begin
        @valids = valid_generator(@player.hand.dominoes, @board)
        puts "valids for player are #{@valids.to_s}"
        inp = get_play
        valid_play = handle_play_input(inp)
        if valid_play
          adjust_score
          adjust_probability_table
        end
      rescue BadInputError => e
        puts "Malformed Input: #{e.message}"
        valid_play = false
      end
    end
    
  end
  
  def opps_turn
    @valids = valid_generator(@pool.dominoes, @board)
    puts "valids for opponent are #{@valids.to_s}"
    puts "Hand size is #{@opp.hand.size}"
    
    while !(valid_play ||= false)
      begin
        inp = get_play
        valid_play = handle_play_input(inp)
        adjust_score
        adjust_probability_table
      rescue BadInputError => e
        puts "Malformed Input: #{e.message}"
        valid_play = false
      end
    end
  end
  
  def log_state
    
  end
  
  def init_logger
    FileUtils.rm_f 'etc/logfile.log'
    $logger = Logger.new('logfile.log')
    $debug ? ($logger.level = Logger::DEBUG) : ($logger.level = Logger::INFO)
  end
  
end